/* 
 * File:   Repositorio.h
 * Author: gabilan
 *
 * Created on 24 de mayo de 2013, 19:33
 */

#ifndef REPOSITORIO_H
#define	REPOSITORIO_H

#include <string>
#include <iostream>
#include <vector>
#include <stdint.h>
#include "common_RepoItem.h"
#include "common_Excepcion.h"
#include "common_ISerializable.h"
#include "common_Mutex.h"

using namespace std;
using namespace TP;

namespace TP { namespace Archivos { 

#define VERSION_NULA 0
    
typedef vector<RepoItem*> SetRepoItem;

typedef vector<RepoItem*>::iterator SetRepoItemIterator;

/**
 * @class Repositorio
 * Administra el Directorio de Archivos Ubicuos
 */
class Repositorio : public ISerializable {
public:
    
    
    Repositorio (const string &pPath);
    
    virtual ~Repositorio();
    
    /**
     * @brief Obtiene el directorio AU
     * @return Directorio AU
     */
    string GetPath() const{
        return this->_path;
    }
    
    /**
     * @brief Inserta un objeto RepoItem a la lista de items
     * @param r Puntero al objeto Repo Item
     * @return VOID
     */
    void AgregarRepoItem(RepoItem * r){
        r->SetFilePath(_path);
        this->lista_archs.push_back(r);    
    }
    
    /**
     * @brief Verifica la existencia de un RepoItem
     * @param filename nombre del archivo a verificar
     * @return true si existe, false si no existe
     */
    bool ExisteRepoItem(const string & filename);
    
    /**
     * @brief Obtiene un RepoItem a traves de un full path
     * @param path path completo del archivo
     * @return Puntero al objeto RepoItem que encapsula al archivo
     */
    RepoItem * GetRepoItemByPath(const string & path);
    
     /**
     * @brief Obtiene un RepoItem a traves de un filename
     * @param filename Nombre del archivo
     * @return Puntero al objeto RepoItem que encapsula al archivo
     */
    RepoItem * GetRepoItemByFilename(const string & filename);
    
    /**
     * @brief Obtiene el numero de la ultima version del Repositorio
     * @return numero de version
     */
    uint32_t GetVersion();
    
    /**
     * @brief Establece el numero de version del repositorio
     * @param pValor numero de version
     * @return numero de version
     */
    uint32_t SetVersion (const uint32_t &pValor);
    
    /**
     * @brief Obtiene la serializacion en un string del XML de almacenamiento de
     * repositorio
     * @return serializacion del XML de almacenamiento
     */
    string Serializar ();
    
    /**
     * @brief Parsea el string serializado para generar un objeto Repositorio
     * @param pXml string serializado
     * @return Puntero al objeto Repositorio
     */
    static Repositorio* Parse (const string& pXml);
    
    /**
     * @brief Obtiene un iterador al primer RepoItem almacenado
     * @return iterador al primero RepoItem
     */
    SetRepoItemIterator GetItemIterator();
    
    /**
     * @brief Obtiene un iterador al ultimo RepoItem almacenado
     * @return iterador al ultimo RepoItem
     */
    SetRepoItemIterator GetItemIteratorEnd();
    
    /**
     * @brief Genera un RepoItem al detectar un nuevo archivo inicialiando sus 
     * valores
     * @return puntero al objeto RepoItem 
     */
    RepoItem* CrearItem();
    
    /**
     * @brief Obtiene un puntero al primer RepoItem almacenado
     * @return puntero al primer RepoItem
     */
    RepoItem* Primero ();
    
    /**
     * @brief obtiene el RepoItem almacenado siguiente al que se le pasa por
     * parámetro
     * @param pRepoItem Puntero al RepoItem actual
     * @return Puntero al RepoItem siguiente
     */
    RepoItem* Siguiente (RepoItem* pRepoItem);
    
private:
    
    uint32_t _version;
    string _path;
    SetRepoItem lista_archs;
    Mutex _lista_archs_Mutex;
    
    // Constantes de serializacion 
    static std::string _rootNodeName;
    static std::string _versionNodeName;
    static std::string _pathNodeName;
    static std::string _listOfRepoItemNodeName;        
};

}}

#endif	/* REPOSITORIO_H */

